package com.k8.registry.listener;

import com.k8.common.event.Event;
import com.k8.common.event.SynListener;
import com.k8.rpc.directory.DynamicDirectory;
import com.k8.rpc.metadata.AppMetaData;
import com.k8.rpc.url.URL;

import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

import static com.k8.common.constants.CommonKeyConstants.RegistryKeyConstant.SERVICE_INSTANCES_KEY;
import static com.k8.common.constants.CommonKeyConstants.RpcKeyConstant.API_SIGNATURE_KEY;

public class InstanceListener implements SynListener {
    private final Map<String, DynamicDirectory<?>> directoryMap;

    //todo 找到对应的目录，故此在服务发现的调用中，需要将包含所有类型的动态目录进行传递
    public InstanceListener(Map<String, DynamicDirectory<?>> directoryMap) {
        this.directoryMap = directoryMap;

    }

    private Lock lock = new ReentrantLock();

    @Override
    public boolean canDispose(Event event) {
        if (event instanceof InstanceEvent) return true;
        return false;
    }

    @Override
    public boolean judgeEventType(Event event) {
        return true;
    }

    @Override
    public void disposal(Event event) {
        InstanceEvent instanceEvent = (InstanceEvent) event;
        URL protocolUrl = instanceEvent.getValue();
        Map<Long, AppMetaData> idMaps = instanceEvent.getIdMaps();
        String apiSignature = instanceEvent.getApiSignature();
        DynamicDirectory<?> dynamicDirectory = directoryMap.get(apiSignature);
        dynamicDirectory.judgeInstanceIsAliveAndCreateNew(idMaps, protocolUrl);
    }

    @Override
    public Lock getLock() {
        return this.lock;
    }

    public static class InstanceEvent implements Event {
        private Throwable exception;
        private URL url;
        private Map<Long, AppMetaData> idMaps;
        private String apiSignature;

        public InstanceEvent(URL url) {
            this.url = url;
        }

        public InstanceEvent(URL url, Map<Long, AppMetaData> idMaps, String apiSignature) {
            this.url = url;
            this.idMaps = idMaps;
            this.apiSignature = apiSignature;
        }

        @Override
        public Throwable getException() {
            return null;
        }

        public void setException(Throwable exception) {
            this.exception = exception;
        }

        @Override
        public URL getValue() {
            return this.url;
        }

        public Map<Long, AppMetaData> getIdMaps() {
            return idMaps;
        }

        public String getApiSignature() {
            return apiSignature;
        }
    }

}
